package com.siki.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.siki.dto.user.UserPasswordDTO;
import com.siki.dto.user.UserInfoSaveDTO;
import com.siki.dto.user.UserSignUpDTO;
import com.siki.mapper.EnterpriseMapper;
import com.siki.mapper.GeneralUserMapper;
import com.siki.mapper.TalentPositionMapper;
import com.siki.mapper.UserMapper;
import com.siki.mapper.repo.UserRepo;
import com.siki.pojo.commonEntity.Enterprise;
import com.siki.pojo.commonEntity.GeneralUser;
import com.siki.pojo.commonEntity.SysUser;
import com.siki.pojo.commonEntity.TalentPosition;
import com.siki.pojo.enumeration.common.AuditStatus;
import com.siki.pojo.enumeration.common.EducationClaim;
import com.siki.pojo.enumeration.common.PositionCategory;
import com.siki.pojo.enumeration.common.UserRole;
import com.siki.pojo.enumeration.common.UserSex;
import com.siki.service.UserService;
import com.siki.utils.JsonInfoReturn;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
 * @Author Siki
 * @Date 2020/6/7
 */
@Service
public class UserServiceImpl implements UserService {

    private UserMapper userMapper;
    private GeneralUserMapper generalUserMapper;
    private final TalentPositionMapper talentPositionMapper;
    private final EnterpriseMapper enterpriseMapper;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    public UserServiceImpl(UserMapper userMapper, GeneralUserMapper generalUserMapper, UserRepo userRepo, TalentPositionMapper talentPositionMapper, EnterpriseMapper enterpriseMapper, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userMapper = userMapper;
        this.generalUserMapper = generalUserMapper;
        this.talentPositionMapper = talentPositionMapper;
        this.enterpriseMapper = enterpriseMapper;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    public void signUp(UserSignUpDTO dto) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("account", dto.getAccount());
        SysUser user = userMapper.selectOne(queryWrapper);
        if (user != null && user.getUserRole().equals(UserRole.valueOf(dto.getUserRole()))) {
            throw new RuntimeException("用户名已存在");
        }
        Assert.isTrue(dto.getPassword().equals(dto.getAgainPassword()), "两次密码不相同");

        SysUser sysUser = new SysUser();
        sysUser.setAccount(dto.getAccount());
        sysUser.setPassword(new BCryptPasswordEncoder().encode(dto.getPassword()));
        sysUser.setRealName(dto.getRealName());
        //身份赋予
        setRole(dto.getUserRole(), sysUser);
        userMapper.insertUser(sysUser);
        Optional.ofNullable(sysUser.getGeneralUser()).ifPresent(generalUser -> {
            generalUserMapper.update(generalUser,
                    new UpdateWrapper<GeneralUser>().set("sys_user_id", sysUser.getId()).set("version",1).eq("id",generalUser.getId()));
        });
        Optional.ofNullable(sysUser.getEnterprise()).ifPresent(enterprise -> {
            enterpriseMapper.update(enterprise,
                    new UpdateWrapper<Enterprise>().set("sys_user_id", sysUser.getId()).set("version",1).eq("id",enterprise.getId()));
        });
    }

    @Override
    public SysUser getUser(String id) {
        return getUserById(id);
    }

    @Override
    public void saveUserInfo(UserInfoSaveDTO dto, String id) {
        var user = getUserById(id);
        user.setRealName(dto.getRealName());
        GeneralUser generalUser = user.getGeneralUser();
        Optional.ofNullable(dto.getUserSex()).ifPresent(sex -> {
            generalUser.setUserSex(UserSex.valueOf(sex));
        });
        generalUser.setAddress(dto.getAddress());
        generalUser.setEmail(dto.getEmail());
        generalUser.setAge(dto.getAge());
        generalUser.setAvatarUrl(dto.getAvatarUrl());
        generalUser.setGraduatedSchool(dto.getGraduatedSchool());
        generalUser.setGraduatedDate(dto.getGraduatedDate());
        generalUser.setProfession(dto.getProfession());
        Optional.ofNullable(dto.getEducation()).ifPresent(edu -> {
            generalUser.setEducation(EducationClaim.valueOf(edu));
        });
        generalUser.setIntention(Optional.ofNullable(dto.getIntention())
                .map(PositionCategory::valueOf).orElse(null));
        generalUser.setExpectedCity(dto.getExpectedCity());
        generalUser.setExpectedSalary(dto.getExpectedSalary());
        generalUser.setSelfIntroduction(dto.getSelfIntroduction());
        // 持久化数据
        generalUserMapper.updateById(generalUser);
        userMapper.updateById(user);
    }

    @Override
    public JsonInfoReturn savePassword(UserPasswordDTO dto, String id){
        Assert.isTrue(dto.getAgainPassword()
                .equals(dto.getNewPassword()),"两次输入的密码不一样");
        return Optional.of(getUser(id))
                .filter(user ->
                        bCryptPasswordEncoder.matches(dto.getOldPassword(),user.getPassword()))
                .map(user ->{
                    user.setPassword(bCryptPasswordEncoder.encode(dto.getNewPassword()));
                    userMapper.updateById(user);
                    return JsonInfoReturn.success("密码修改成功");
                })
                .orElse(JsonInfoReturn.fail("旧密码与原密码不一致"));
    }

    @Override
    public List<TalentPosition> getPosition(String id) {
        return talentPositionMapper.queryPositionByUserId(id);
    }

    /**
     * 私有方法
     */

    /**
     * 根据id查询用户实体
     *
     * @param id 用户id
     * @return SysUser 用户实体
     */
    private SysUser getUserById(String id) {
        return Optional.ofNullable(userMapper.selectById(id))
                .orElseThrow(() -> new RuntimeException("该id" + id + "查询不到用户"));
    }

    /**
     * 身份赋予
     *
     * @param role    用户角色
     * @param sysUser 用户实体
     */
    private void setRole(String role, SysUser sysUser) {
        UserRole userRole = UserRole.valueOf(role);
        sysUser.setUserRole(userRole);
        switch (userRole) {
            case GENERAL_USER:
                sysUser.setAuditStatus(AuditStatus.DONT_EXAMINATION);
                GeneralUser generalUser = new GeneralUser();
                generalUserMapper.insert(generalUser);
                sysUser.setGeneralUser(generalUser);
                break;
            case BUSINESS_USER:
                sysUser.setAuditStatus(AuditStatus.UNDER_REVIEW);
                Enterprise enterprise = new Enterprise();
                enterpriseMapper.insert(enterprise);
                sysUser.setEnterprise(enterprise);
                break;
        }
    }
}
